/************************************************************************
 *				SRLOS Team CopyRight
 *@file		task_idmgr.c
 *@author	bloceanc
 *@date		7/17/2010
 *@note		process task ID, including PID,TID.
 ************************************************************************/
 
#include "task.h"

/*
 * COMMENTS:
 * 	manager task identifer.use 4Bytes, high 2Byte used to indicate process id.
 * and low 2Bytes used to indicate thread is of process.
 */

// max count of task including process and thread
#define	MAX_TASK_COUNT	32768	// this value must be reside of 8

// TIDbitmap, task ID bitmap
char TIDBMP[MAX_TASK_COUNT>>3];
int tid_nr;	// next unsed id
k_mutex tidmutex;// mutex for this mode

extern void mt_mutex_initset(k_mutex *mutex);
extern int mt_mutex_lock(k_mutex *mutex, long long time);
extern void mt_mutex_unlock(k_mutex *mutex);

/*
 * initialize module
 */
void task_idmgr_init(void)
{
	unsigned int count = MAX_TASK_COUNT >> 3;
	unsigned int i;
	for(i = 0; i < count; i++)
	{
		TIDBMP[i]=0;
	}
	tid_nr = 0;
	mt_mutex_initset(&tidmutex);
}

/*
 * looking for unused bit.
 *@return -1 if faild, otherwise task id.
 */
static signed int task_find_bit(void)
{
	unsigned int i = 0, j = 0;
	unsigned int cur = 0;
	unsigned int bytecount = MAX_TASK_COUNT >> 3;
	while(i != bytecount)
	{
		if(TIDBMP[i] ^ 0xff)
		{
			cur = TIDBMP[i];
			j = 0;
			while(cur & (unsigned char)~(1<<j))
				j++;
			TIDBMP[i] |= 1<<j;
			return i<<3+j;
		}
		i++;
	}
	return -1;
}

/*
 *	create task id
 */
static signed int task_create_id(void)
{
	signed int id = 0;
	mt_mutex_lock(&tidmutex, -1);
	if(tid_nr == MAX_TASK_COUNT)
	{
		id = task_find_bit();
		if(id == -1)
		{
			// just loop current process.
			while(1);
		}
	}
	else
		id = tid_nr++;

	mt_mutex_unlock(&tidmutex);
	return id;
}

/*
 * release task id
 */
static void task_release_id(int id)
{
	unsigned short tid = id&0xffff;
	mt_mutex_lock(&tidmutex, -1);
	TIDBMP[tid>>3] &= ~(1<<(tid & 0x7));
	mt_mutex_unlock(&tidmutex);
}

/*
 * create process id
 */
int task_pid(void)
{
	return task_create_id();
}

/*
 * create thread id
 */
int task_tid(k_thread *thread)
{
	int id = task_create_id();
	return (thread->process->pid & 0xffff)<<16 | (id & 0xffff);
}

/*
 * release task id
 */
void task_tid_release(unsigned int id)
{
	task_release_id(id);
}

